
package com.jf.cloud.supplier.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.jf.cloud.api.auth.bo.UserInfoInTokenBO;
import com.jf.cloud.api.auth.constant.SysTypeEnum;
import com.jf.cloud.api.auth.dto.AuthAccountDTO;
import com.jf.cloud.api.auth.feign.AccountFeignClient;
import com.jf.cloud.api.auth.vo.AuthAccountVO;
import com.jf.cloud.api.biz.feign.AttachFileFeignClient;
import com.jf.cloud.api.biz.feign.NotifyFeignClient;
import com.jf.cloud.api.feign.SearchSpuFeignClient;
import com.jf.cloud.api.platform.constant.OfflineHandleEventStatus;
import com.jf.cloud.api.platform.constant.OfflineHandleEventType;
import com.jf.cloud.api.platform.dto.OfflineHandleEventDTO;
import com.jf.cloud.api.platform.feign.OfflineHandleEventFeignClient;
import com.jf.cloud.api.platform.vo.OfflineHandleEventVO;
import com.jf.cloud.api.product.feign.BrandFeignClient;
import com.jf.cloud.api.product.feign.BrandShopFeignClient;
import com.jf.cloud.api.product.feign.CategoryShopFeignClient;
import com.jf.cloud.api.product.feign.SpuFeignClient;
import com.jf.cloud.api.supplier.bo.SupplierDetailBO;
import com.jf.cloud.api.supplier.bo.SupplierSimpleBO;
import com.jf.cloud.api.supplier.constant.SupplierStatus;
import com.jf.cloud.api.supplier.vo.SupplierApiDetailVO;
import com.jf.cloud.common.cache.constant.CacheNames;
import com.jf.cloud.common.cache.util.RedisUtil;
import com.jf.cloud.common.constant.IsPassShopEnum;
import com.jf.cloud.common.constant.SendTypeEnum;
import com.jf.cloud.common.constant.StatusEnum;
import com.jf.cloud.common.constant.UserAdminType;
import com.jf.cloud.common.database.dto.PageDTO;
import com.jf.cloud.common.database.util.PageUtil;
import com.jf.cloud.common.database.vo.PageVO;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.product.dto.ProductSearchLimitDTO;
import com.jf.cloud.common.product.vo.search.SpuSearchVO;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.common.util.IpHelper;
import com.jf.cloud.supplier.constant.AuditStatus;
import com.jf.cloud.supplier.constant.SupplierType;
import com.jf.cloud.supplier.constant.SupplierWalletZoneConstant;
import com.jf.cloud.supplier.dto.*;
import com.jf.cloud.supplier.mapper.SupplierDetailMapper;
import com.jf.cloud.supplier.mapper.SupplierUserMapper;
import com.jf.cloud.supplier.mapper.SupplierWalletMapper;
import com.jf.cloud.supplier.model.*;
import com.jf.cloud.supplier.service.*;
import com.jf.cloud.supplier.vo.SupplierAuditingVO;
import com.jf.cloud.supplier.vo.SupplierCompanyVO;
import com.jf.cloud.supplier.vo.SupplierDetailAppVO;
import com.jf.cloud.supplier.vo.SupplierDetailVO;
import io.seata.spring.annotation.GlobalTransactional;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 供应商详情
 *
 * @author zz
 * @date 2022-03-14 17:04:32
 */
@Service
public class SupplierDetailServiceImpl implements SupplierDetailService {

    @Autowired
    private SupplierDetailMapper supplierDetailMapper;
    @Autowired
    private CategoryShopFeignClient categoryShopFeignClient;
    @Autowired
    private SupplierCompanyService supplierCompanyService;
    @Autowired
    private SupplierAuditingService supplierAuditingService;
    @Autowired
    private SearchSpuFeignClient searchSpuFeignClient;
    @Autowired
    private SupplierWalletMapper supplierWalletMapper;
    @Autowired
    private SupplierUserService supplierUserService;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private SupplierExtensionService supplierExtensionService;
    @Autowired
    private AccountFeignClient accountFeignClient;
    @Autowired
    private SpuFeignClient spuFeignClient;
    @Autowired
    private SupplierUserMapper supplierUserMapper;
    @Autowired
    private BrandFeignClient brandFeignClient;
    @Autowired
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;
    @Autowired
    private NotifyFeignClient notifyFeignClient;
    @Autowired
    private SupplierBankCardService supplierBankCardService;
    @Autowired
    private BrandShopFeignClient brandSupplierFeignClient;
    @Autowired
    private AttachFileFeignClient attachFileFeignClient;


    @Override
    public PageVO<SupplierApiDetailVO> page(PageDTO pageDTO, SupplierDetailDTO supplierDetailDTO) {
        return PageUtil.doPage(pageDTO, () -> supplierDetailMapper.list(supplierDetailDTO));
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierId")
    public SupplierApiDetailVO getBySupplierId(Long supplierId) {
        SupplierApiDetailVO supplierApiDetailVO = supplierDetailMapper.getBySupplierId(supplierId);
        ServerResponseEntity<AuthAccountVO> responseEntity = accountFeignClient.getAccountInfoByTenantId(supplierId, SysTypeEnum.SUPPLIER.value());
        if (responseEntity.isSuccess() && Objects.nonNull(responseEntity.getData())) {
            AuthAccountVO authAccountVO = responseEntity.getData();
            supplierApiDetailVO.setAccountStatus(authAccountVO.getStatus());
        }
        return supplierApiDetailVO;
    }

    @Override
    public void save(SupplierDetail supplierDetail) {
        supplierDetailMapper.save(supplierDetail);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierDetailDTO.supplierId")
    public void update(SupplierDetailDTO supplierDetailDTO) {
        this.checkSupplierInfo(supplierDetailDTO, false);
        SupplierDetail supplierDetail = mapperFacade.map(supplierDetailDTO, SupplierDetail.class);
        // 更新商品
        spuFeignClient.updateSpuByShopId(supplierDetail.getSupplierId(), SysTypeEnum.SUPPLIER.value());
        supplierDetailMapper.update(supplierDetail);
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierId")
    public void deleteById(Long supplierId) {
        supplierDetailMapper.deleteById(supplierId);
    }

    @Override
    public List<SupplierDetail> listBySupplierIds(List<Long> supplierIds) {
        if (CollUtil.isEmpty(supplierIds)) {
            return new ArrayList<>();
        }
        return supplierDetailMapper.listBySupplierIds(supplierIds);
    }

    @Override
    public PageVO<SupplierDetailAppVO> supplierSearchPage(PageDTO pageDTO, SupplierDetailDTO supplierDetailDTO) {
        PageVO<SupplierDetailAppVO> page = PageUtil.doPage(pageDTO, () -> supplierDetailMapper.supplierSearchList(supplierDetailDTO));
        Set<Long> spuIdSet = page.getList().stream().map(SupplierDetailAppVO::getSupplierId).collect(Collectors.toSet());
        if (Objects.isNull(supplierDetailDTO.getSpuNum()) || supplierDetailDTO.getSpuNum() <= 0) {
            return page;
        }
        ProductSearchLimitDTO productSearchLimitDTO = new ProductSearchLimitDTO(supplierDetailDTO.getSpuNum());
        productSearchLimitDTO.setSupplierIds(new ArrayList<>(spuIdSet));
        ServerResponseEntity<List<SpuSearchVO>> spuResponse = searchSpuFeignClient.limitSpuList(productSearchLimitDTO);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        } else if (CollectionUtil.isEmpty(spuResponse.getData())) {
            return page;
        }
        List<SpuSearchVO> data = spuResponse.getData();
        Map<Long, List<SpuSearchVO>> supplierMap = data.stream().collect(Collectors.groupingBy(SpuSearchVO::getSupplierId));
        for (SupplierDetailAppVO supplierDetail : page.getList()) {
            List<SpuSearchVO> spuSearchVOList = supplierMap.get(supplierDetail.getSupplierId());
            if (CollUtil.isEmpty(spuSearchVOList)) {
                spuSearchVOList = new ArrayList<>();
            }
            supplierDetail.setSpuList(spuSearchVOList);
        }
        return page;
    }

    @Override
    public SupplierApiDetailVO getSupplierBySupplierId(Long supplierId) {
        return supplierDetailMapper.getSupplierBySupplierId(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional
    public void applySupplier(SupplierDetailDTO supplierDetailDTO) {
        checkSupplierInfo(supplierDetailDTO, true);
        SupplierDetail newSupplierDetail = mapperFacade.map(supplierDetailDTO, SupplierDetail.class);
        // 申请开店
        newSupplierDetail.setSupplierStatus(SupplierStatus.APPLYING.value());
        newSupplierDetail.setType(SupplierType.STOP.value());
        supplierDetailMapper.save(newSupplierDetail);
        supplierDetailDTO.setSupplierId(newSupplierDetail.getSupplierId());

        // 插入一条审核记录
        SupplierAuditing auditing = new SupplierAuditing();
        auditing.setSupplierId(newSupplierDetail.getSupplierId());
        auditing.setCreateTime(new Date());
        auditing.setStatus(AuditStatus.WAITAUDIT.value());
        auditing.setUpdateTime(new Date());
        auditing.setRemarks(supplierDetailDTO.getRemarks());
        supplierAuditingService.save(auditing);
        // 创建账号
        createSupplierAccount(supplierDetailDTO, StatusEnum.DELETE);
    }

    /**
     * 审核供应商信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void audit(SupplierAuditingDTO supplierAuditingDTO) {
        Date now = new Date();
        SupplierAuditingVO dbSupplierAyditing = supplierAuditingService.getBySupplierId(supplierAuditingDTO.getSupplierId());
        if (Objects.isNull(dbSupplierAyditing)) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }
        supplierAuditingDTO.setSupplierAuditingId(dbSupplierAyditing.getSupplierAuditingId());
        // 非待审核的供应商，不能再进行审核
        if (!Objects.equals(dbSupplierAyditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
            throw new LuckException(ResponseEnum.DATA_ERROR);
        }

        // 修改供应商状态
        SupplierApiDetailVO supplierApiDetailVO = getBySupplierId(supplierAuditingDTO.getSupplierId());
        if (supplierApiDetailVO == null) {
            // 供应商信息不存在
            throw new LuckException("供应商信息不存在");
        }
        Long supplierUserId = supplierUserService.getUserIdBySupplierId(supplierApiDetailVO.getSupplierId());

        SupplierDetail supplierDetail = mapperFacade.map(supplierApiDetailVO, SupplierDetail.class);
        UserInfoInTokenBO userInfoInTokenBO = new UserInfoInTokenBO();
        userInfoInTokenBO.setUserId(supplierUserId);
        userInfoInTokenBO.setSysType(SysTypeEnum.SUPPLIER.value());
        userInfoInTokenBO.setTenantId(supplierAuditingDTO.getSupplierId());
        userInfoInTokenBO.setIsAdmin(UserAdminType.ADMIN.value());
        // 审核不通过
        if (Objects.equals(supplierAuditingDTO.getStatus(), AuditStatus.FAILAUDIT.value())) {
            supplierDetail.setSupplierStatus(SupplierStatus.APPLYING.value());
        }
        // 审核通过
        else {
            supplierDetail.setType(supplierAuditingDTO.getSupplierType());
            supplierDetail.setContractStartTime(DateUtil.beginOfDay(supplierAuditingDTO.getContractStartTime()));
            supplierDetail.setContractEndTime(getSaveEndOfDay(supplierAuditingDTO.getContractEndTime()));
            if (now.compareTo(supplierDetail.getContractStartTime()) >= 0 && now.compareTo(supplierDetail.getContractEndTime()) < 0) {
                // 如果供应商的签约时间包含当前时间，则把供应商状态置为营业中
                supplierDetail.setSupplierStatus(SupplierStatus.OPEN.value());
            } else {
                // 如果供应商的签约时间不包含当前时间，则把供应商状态置为停业中
                supplierDetail.setSupplierStatus(SupplierStatus.STOP.value());
            }
            supplierDetail.setIsPreferred(IsPassShopEnum.NO.value());
            updateSupplierCompanyStatus(supplierDetail.getSupplierId(), AuditStatus.SUCCESSAUDIT.value());
            userInfoInTokenBO.setIsPassShop(IsPassShopEnum.YES.value());
            ServerResponseEntity<Void> updateTenantIdRes = accountFeignClient.updateUserInfoByUserIdAndSysType(userInfoInTokenBO, supplierUserId, SysTypeEnum.SUPPLIER.value());
            if (!updateTenantIdRes.isSuccess()) {
                throw new LuckException("审核失败");
            }
            // 把商家自定义品牌添加为平台品牌
            brandFeignClient.updateCustomBrandToPlatformBrandByShopId(supplierAuditingDTO.getSupplierId(), SysTypeEnum.SUPPLIER.value());
            // 新店初始化事件 (分销设置（暂无）), 分销设置是平台统一设置，供应商暂无分销设置
        }
        supplierAuditingDTO.setAuditorId(AuthUserContext.get().getUserId());
        supplierAuditingService.update(mapperFacade.map(supplierAuditingDTO, SupplierAuditing.class));
        supplierDetailMapper.update(supplierDetail);
    }

    /**
     *  更新供应商工商信息审核状态
     * @param supplierId
     * @param status
     */
    private void updateSupplierCompanyStatus(Long supplierId, Integer status) {

        SupplierCompanyVO supplierCompanyWaitAudit = supplierCompanyService.getSupplierCompanyBySupplierIdAndStatus(supplierId, AuditStatus.WAITAUDIT.value());
        if (Objects.isNull(supplierCompanyWaitAudit)){
                throw new LuckException("缺少店铺工商资料");
        }
        SupplierCompany supplierCompany = mapperFacade.map(supplierCompanyWaitAudit, SupplierCompany.class);
        supplierCompany.setStatus(status);
        supplierCompanyService.updateBySupplierId(supplierCompany, supplierId, 0);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional
    public void changeSpuStatus(Long supplierId, Integer supplierStatus) {
        supplierDetailMapper.changeSupplierStatus(supplierId, supplierStatus);
        // 供应商
        if (!StatusEnum.offlineOrDelete(supplierStatus)) {
            return;
        }
        // 将该供应商所有的商品下线
        ServerResponseEntity<Void> spuResponse = spuFeignClient.offlineSpuByShopId(supplierId);
        if (!Objects.equals(spuResponse.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(spuResponse.getMsg());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierId")
    public void removeCacheBySupplierId(Long supplierId) {

    }

    @Override
    public SupplierDetailBO supplierExtensionData(Long supplierId) {
        return supplierDetailMapper.supplierExtensionData(supplierId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void createSupplier(SupplierDetailDTO supplierDetailDTO) {
        checkSupplierInfo(supplierDetailDTO, true);
        SupplierDetail supplierDetail = mapperFacade.map(supplierDetailDTO, SupplierDetail.class);
        // 赋默认值
        supplierDetail.setType(SupplierType.STOP.value());
        supplierDetail.setSupplierStatus(SupplierStatus.APPLYING.value());
        supplierDetailMapper.save(supplierDetail);

        // 创建供应商数据
        addSupplierInfo(supplierDetail.getSupplierId());

        Long supplierUserId = AuthUserContext.get().getUserId();
        // 更新文件记录表中supplierId
        ServerResponseEntity<Void> attachRes = attachFileFeignClient.updateShopIdByUid(supplierDetail.getSupplierId());
        if (attachRes.isFail()) {
            throw new LuckException(attachRes.getMsg());
        }
        // 保存supplierId到供应商用户表
        if (supplierUserMapper.updateSupplierIdBySupplierUserId(supplierDetail.getSupplierId(), supplierUserId) != 1) {
            throw new LuckException("保存供应商信息错误");
        }
        // 保存supplierId到账号表
        UserInfoInTokenBO userInfoInTokenBO = AuthUserContext.get();
        userInfoInTokenBO.setTenantId(supplierDetail.getSupplierId());
        ServerResponseEntity<Void> updateTenantIdRes = accountFeignClient.updateUserInfoByUserIdAndSysType(userInfoInTokenBO, supplierUserId, SysTypeEnum.SUPPLIER.value());
        if (!updateTenantIdRes.isSuccess()) {
            throw new LuckException(updateTenantIdRes.getMsg());
        }
    }

    @Override
    public List<SupplierApiDetailVO> getSupplierDetailBySupplierIdAndSupplierName(List<Long> supplierIds, String supplierName) {
        return supplierDetailMapper.getSupplierDetailBySupplierIdAndSupplierName(supplierIds,supplierName);
    }

    @Override
    public SupplierApiDetailVO getShoExtensionsBySupplierId(Long supplierId) {
        return supplierDetailMapper.getShoExtensionsBySupplierId(supplierId);
    }

    @Override
    public Integer countByMobile(String mobile) {
        return supplierDetailMapper.countByMobile(mobile);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierApiDetailVO.supplierId")
    @GlobalTransactional(rollbackFor = Exception.class)
    public void offline(SupplierApiDetailVO supplierApiDetailVO, String offlineReason, Long sysUserId) {
        Integer sysType = SysTypeEnum.SUPPLIER.value();
        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEventDTO offlineHandleEventDTO = new OfflineHandleEventDTO();
        offlineHandleEventDTO.setHandleId(supplierApiDetailVO.getSupplierId());
        offlineHandleEventDTO.setHandleType(OfflineHandleEventType.SHOP.getValue());
        offlineHandleEventDTO.setOfflineReason(offlineReason);
        offlineHandleEventDTO.setHandlerId(sysUserId);
        offlineHandleEventDTO.setSysType(sysType);
        offlineHandleEventDTO.setStatus(OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEventDTO.setShopId(supplierApiDetailVO.getSupplierId());
        ServerResponseEntity<OfflineHandleEventVO> processingEventByHandleTypeAndHandleId = offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.SHOP.getValue(), supplierApiDetailVO.getSupplierId(), sysType);
        if (processingEventByHandleTypeAndHandleId.isSuccess() && Objects.nonNull(processingEventByHandleTypeAndHandleId.getData())) {
            offlineHandleEventFeignClient.update(offlineHandleEventDTO);
        } else {
            offlineHandleEventFeignClient.save(offlineHandleEventDTO);
        }
        // 更新供应商状态为下线
        supplierDetailMapper.changeSupplierStatus(supplierApiDetailVO.getSupplierId(), SupplierStatus.OFFLINE.value());

        // 将供应商所有商品下线
        ServerResponseEntity<Void> spuResponseEntity = spuFeignClient.offlineSpuBySupplierId(supplierApiDetailVO.getSupplierId());
        if (spuResponseEntity.isFail()) {
            throw new LuckException(spuResponseEntity);
        }
    }

    private void offlineIndexImg(Long supplierId) {
        ServerResponseEntity<List<Long>> spuIdsEntity = spuFeignClient.listSpuIdsByShopId(supplierId);
        if (spuIdsEntity.isFail()) {
            throw new LuckException(spuIdsEntity.getMsg());
        }
        List<Long> spuIds = spuIdsEntity.getData();
//        if (CollUtil.isNotEmpty(spuIds)) {
//            indexImgService.offlineSpuBySpuIds(Constant.PLATFORM_SHOP_ID, spuIds);
//        }
    }

    @Override
    public Long countBySupplierStatus(Long supplierStatus) {
        return supplierDetailMapper.countBySupplierStatus(supplierStatus);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void platformCreateSupplier(SupplierCreateInfoDTO supplierCreateInfoDTO) {
        SupplierUserRegisterDTO supplierUserRegisterInfo = supplierCreateInfoDTO.getSupplierUserRegisterInfo();
        // 校验用户信息
        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setPhone(supplierUserRegisterInfo.getMobile());
        authAccountDTO.setIsAdmin(UserAdminType.ADMIN.value());
        authAccountDTO.setUsername(supplierUserRegisterInfo.getUsername());
        authAccountDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        authAccountDTO.setStatus(StatusEnum.ENABLE.value());
        ServerResponseEntity<Boolean> verifyAccountResponse = accountFeignClient.verifyAccount(authAccountDTO);
        if (!verifyAccountResponse.isSuccess()) {
            throw new LuckException(verifyAccountResponse.getMsg());
        }

        // 1、校验验证码信息
        ServerResponseEntity<Boolean> sendNotifyResponse = notifyFeignClient.checkValidCode(supplierUserRegisterInfo.getMobile(), supplierUserRegisterInfo.getValidCode(), SendTypeEnum.VALID);
        Boolean data = sendNotifyResponse.getData();
        if (Objects.equals(sendNotifyResponse.getCode(), ResponseEnum.OK.value()) && Objects.nonNull(data) && !data) {
            throw new LuckException("验证码有误或已过期");
        }
        // 2、保存供应商基本信息
        Date now = new Date();
        SupplierDetailDTO supplierDetailDTO = supplierCreateInfoDTO.getSupplierDetail();
        this.checkSupplierInfo(supplierDetailDTO, true);
        SupplierDetail supplierDetail = mapperFacade.map(supplierDetailDTO, SupplierDetail.class);
        if (Objects.isNull(supplierDetail.getContractStartTime()) || Objects.isNull(supplierDetail.getContractEndTime())) {
            throw new LuckException("供应商签约时间不能为空");
        }
        supplierDetail.setContractStartTime(DateUtil.beginOfDay(supplierDetail.getContractStartTime()));
        supplierDetail.setContractEndTime(getSaveEndOfDay(supplierDetail.getContractEndTime()));
        supplierDetail.setIsPreferred(IsPassShopEnum.NO.value());
        if (now.compareTo(supplierDetail.getContractStartTime()) >= 0 && now.compareTo(supplierDetail.getContractEndTime()) < 0) {
            // 如果供应商的签约时间包含当前时间，则把供应商状态置为营业中
            supplierDetail.setSupplierStatus(SupplierStatus.OPEN.value());
        } else {
            // 如果供应商的签约时间不包含当前时间，则把供应商状态置为停业中
            supplierDetail.setSupplierStatus(SupplierStatus.STOP.value());
        }
        supplierDetailMapper.save(supplierDetail);
        Long supplierId = supplierDetail.getSupplierId();
        // 3、保存供应商账号信息
        SupplierUser supplierUser = new SupplierUser();
        supplierUser.setNickName(supplierUserRegisterInfo.getUsername());
        supplierUser.setPhoneNum(supplierUserRegisterInfo.getMobile());
        supplierUser.setHasAccount(1);
        supplierUser.setSupplierId(supplierId);
        supplierUserService.save(supplierUser, null);

        authAccountDTO.setTenantId(supplierId);
        authAccountDTO.setUserId(supplierUser.getSupplierUserId());
        authAccountDTO.setPassword(supplierUserRegisterInfo.getPassword());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setIsPassShop(IsPassShopEnum.YES.value());
        ServerResponseEntity<Long> save = accountFeignClient.save(authAccountDTO);
        if (!Objects.equals(save.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(save.getMsg());
        }
        // 4、初始化供应商数据
        addSupplierInfo(supplierId);
        // 5、初始化供应商审核信息，平台端创建供应商默认为审核成功
        SupplierAuditing supplierAuditing = new SupplierAuditing();
        supplierAuditing.setSupplierId(supplierId);
        supplierAuditing.setUserId(supplierUser.getSupplierUserId());
        supplierAuditing.setAuditorId(AuthUserContext.get().getUserId());
        supplierAuditing.setStatus(AuditStatus.SUCCESSAUDIT.value());
        supplierAuditingService.save(supplierAuditing);
        // 6、保存供应商工商信息
        SupplierCompanyDTO supplierCompanyDTO = supplierCreateInfoDTO.getSupplierCompany();
        supplierCompanyDTO.setSupplierId(supplierDetail.getSupplierId());
        SupplierCompany supplierCompany = mapperFacade.map(supplierCompanyDTO, SupplierCompany.class);
        supplierCompany.setStatus(AuditStatus.SUCCESSAUDIT.value());
        supplierCompanyService.save(supplierCompany, true);
        // 7、保存供应商银行卡信息
        supplierBankCardService.insertBatch(supplierCreateInfoDTO.getSupplierBankCardList(), supplierId);
        // 8、保存分类签约信息
        ServerResponseEntity<Void> categoryRes = categoryShopFeignClient.insertBatchByShopId(supplierCreateInfoDTO.getCategorySigningList(), supplierId, SysTypeEnum.SUPPLIER.value());
        if (!categoryRes.isSuccess()) {
            throw new LuckException(categoryRes.getMsg());
        }
        // 9、保存品牌签约信息
        ServerResponseEntity<Void> brandRes = brandSupplierFeignClient.insertBatchByShopId(supplierCreateInfoDTO.getBrandSigningList(), supplierId, SysTypeEnum.SUPPLIER.value());
        if (!brandRes.isSuccess()) {
            throw new LuckException(brandRes.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    public void changeSupplierStatusByContractTime(Date now) {
        // 获取状态需要改变为停业状态的供应商id列表
        List<Long> supplierIdsToStop = supplierDetailMapper.listSupplierIdsOfStatusChangeToStopByContractTime(now);
        // 获取状态需要改变为营业状态的供应商id列表
        List<Long> supplierIdsToOpen = supplierDetailMapper.listSupplierIdsOfStatusChangeToOpenByContractTime(now);
        if (CollUtil.isEmpty(supplierIdsToStop) && CollUtil.isEmpty(supplierIdsToOpen)) {
            // 没有供应商状态需要改变
            return;
        }
        // 根据签约时间修改供应商状态
        supplierDetailMapper.changeSupplierStatusByContractTime(now);
        if (CollUtil.isNotEmpty(supplierIdsToStop)) {
            // 失效商品活动信息，不需要下架商品
            spuFeignClient.offlineSpuActivityByShopIds(supplierIdsToStop);
            //供应商为停业状态，下架供应商商品
            spuFeignClient.batchChangeSpuStatusToDisableBySupplierIds(supplierIdsToStop);
        }
        // 状态发生变化的供应商id列表
        List<Long> changeSupplierIds = CollUtil.unionAll(supplierIdsToStop, supplierIdsToOpen);
        // 清除状态发生变化的供应商缓存信息
        List<String> keyList = new ArrayList<>();
        changeSupplierIds.forEach(supplierId -> {
            keyList.add(CacheNames.SUPPLIER_DETAIL_ID_KEY + CacheNames.UNION + supplierId);
        });
        if (CollUtil.isNotEmpty(keyList)) {
            RedisUtil.deleteBatch(keyList);
        }
        // 更新供应商下的商品更新时间（用于刷新商品在es的appDisplay）
        ServerResponseEntity<Void> spuRes = spuFeignClient.updateSpuUpdateTimeByShopIds(changeSupplierIds, SysTypeEnum.SUPPLIER.value());
        if (spuRes.isFail()) {
            throw new LuckException(spuRes.getMsg());
        }
//        // 修改购物车项中供应商是否停业属性
//        ServerResponseEntity<Void> supplierCartToStopRes = shopCartFeignClient.updateIsClosedBySupplierIds(supplierIdsToStop, 0);
//        if (supplierCartToStopRes.isFail()) {
//            throw new LuckException(supplierCartToStopRes.getMsg());
//        }
//        ServerResponseEntity<Void> supplierCartToOpenRes = shopCartFeignClient.updateIsClosedBySupplierIds(supplierIdsToOpen, 1);
//        if (supplierCartToOpenRes.isFail()) {
//            throw new LuckException(supplierCartToOpenRes.getMsg());
//        }
        // 下线优惠券满减活动
        offlineSupplierActivity(supplierIdsToStop, SupplierStatus.STOP.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#supplierSigningInfoDTO.supplierId")
    public void updateSigningInfo(SupplierSigningInfoDTO supplierSigningInfoDTO) {
        SupplierApiDetailVO oldSupplierDetail = supplierDetailMapper.getBySupplierId(supplierSigningInfoDTO.getSupplierId());
        SupplierDetail newSupplierDetail = mapperFacade.map(oldSupplierDetail, SupplierDetail.class);
        // 赋值
        newSupplierDetail.setType(supplierSigningInfoDTO.getType());
        newSupplierDetail.setContractStartTime(DateUtil.beginOfDay(supplierSigningInfoDTO.getContractStartTime()));
        newSupplierDetail.setContractEndTime(getSaveEndOfDay(supplierSigningInfoDTO.getContractEndTime()));
        // 当供应商状态处于营业中或者停业中时，供应商状态会受签约时间改变
        if (Objects.equals(newSupplierDetail.getSupplierStatus(), SupplierStatus.OPEN.value()) || Objects.equals(newSupplierDetail.getSupplierStatus(), SupplierStatus.STOP.value())) {
            Date now = new Date();
            // 记录供应商状态是否发生改变
            boolean isChangeStatus = false;
            if (now.compareTo(newSupplierDetail.getContractStartTime()) >= 0 && now.compareTo(newSupplierDetail.getContractEndTime()) < 0) {
                // 如果供应商的签约时间包含当前时间，则把供应商状态置为营业中
                isChangeStatus = Objects.equals(oldSupplierDetail.getSupplierStatus(), SupplierStatus.STOP.value());
                newSupplierDetail.setSupplierStatus(SupplierStatus.OPEN.value());
                supplierDetailMapper.update(newSupplierDetail);
                ServerResponseEntity<Void> spuRes = spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(supplierSigningInfoDTO.getSupplierId()), SysTypeEnum.SUPPLIER.value());
                if (spuRes.isFail()) {
                    throw new LuckException(spuRes.getMsg());
                }
            } else if (now.compareTo(newSupplierDetail.getContractStartTime()) < 0 || now.compareTo(newSupplierDetail.getContractEndTime()) >= 0) {
                // 如果供应商的签约时间不包含当前时间，则把供应商状态置为停业中
                isChangeStatus = Objects.equals(oldSupplierDetail.getSupplierStatus(), SupplierStatus.OPEN.value());
                newSupplierDetail.setSupplierStatus(SupplierStatus.STOP.value());
                supplierDetailMapper.update(newSupplierDetail);
            }
            //  供应商商品不能参加活动，不需要进行以下处理

//            // 如果供应商状态发生变化
            if (isChangeStatus) {
                // 更新购物车项供应商是否停业状态
//                ServerResponseEntity<Void> supplierCartRes = supplierCartFeignClient.updateIsClosedBySupplierIds(Collections.singletonList(newSupplierDetail.getSupplierId()), Objects.equals(newSupplierDetail.getSupplierStatus(), SupplierStatus.STOP.value()) ? 0 : 1);
//                if (supplierCartRes.isFail()) {
//                    throw new LuckException(supplierCartRes.getMsg());
//                }
                if (Objects.equals(oldSupplierDetail.getSupplierStatus(), SupplierStatus.OPEN.value())) {
                    // 供应商营业状态变为停业，需要下架供应商商品
                    ServerResponseEntity<Void> toDisableRes = spuFeignClient.batchChangeSpuStatusToDisableBySupplierIds(Collections.singletonList(newSupplierDetail.getSupplierId()));
                    if (toDisableRes.isFail()) {
                        throw new LuckException(toDisableRes.getMsg());
                    }
                }
            }
        }
        //解绑平台轮播图商品
//        offlineIndexImg(newSupplierDetail.getSupplierId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void auditApply(OfflineHandleEventDTO offlineHandleEventDTO) {
        SupplierApiDetailVO supplierApiDetailVO = getBySupplierId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(supplierApiDetailVO)) {
            throw new LuckException("供应商不存在");
        }
        if (!Objects.equals(supplierApiDetailVO.getSupplierStatus(), SupplierStatus.OFFLINE.value())) {
            throw new LuckException("供应商状态已发生变化，请刷新后重试");
        }
        // 更新事件状态
        ServerResponseEntity<Void> offlineRes = offlineHandleEventFeignClient.updateToApply(offlineHandleEventDTO);
        if (offlineRes.isFail()) {
            throw new LuckException(offlineRes.getMsg());
        }
        // 更改供应商状态为上线申请待审核
        supplierDetailMapper.changeSupplierStatus(offlineHandleEventDTO.getHandleId(), SupplierStatus.OFFLINE_AWAIT_AUDIT.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @GlobalTransactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SUPPLIER_DETAIL_ID_KEY, key = "#offlineHandleEventDTO.handleId")
    public void onlineAudit(OfflineHandleEventDTO offlineHandleEventDTO) {
        SupplierApiDetailVO supplierDetail = getBySupplierId(offlineHandleEventDTO.getHandleId());
        if (Objects.isNull(supplierDetail)) {
            throw new LuckException("供应商不存在");
        }
        if (!Objects.equals(supplierDetail.getSupplierStatus(), SupplierStatus.OFFLINE_AWAIT_AUDIT.value())) {
            throw new LuckException("供应商状态已发生变化，请刷新后重试");
        }
        // 审核
        ServerResponseEntity<Void> responseEntity = offlineHandleEventFeignClient.auditOfflineEvent(offlineHandleEventDTO);
        if (!Objects.equals(responseEntity.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(responseEntity.getMsg());
        }
        Date now = new Date();
        Long supplierId = offlineHandleEventDTO.getHandleId();
        // 审核通过
        if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            if (now.compareTo(supplierDetail.getContractStartTime()) >= 0 && now.compareTo(supplierDetail.getContractEndTime()) < 0) {
                // 如果供应商的签约时间包含当前时间，则把供应商状态置为营业中
                supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.OPEN.value());
            } else {
                // 如果供应商的签约时间不包含当前时间，则把供应商状态置为停业中
                supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.STOP.value());
            }
            spuFeignClient.updateSpuUpdateTimeByShopIds(Collections.singletonList(supplierId), SysTypeEnum.SUPPLIER.value());
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventDTO.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            supplierDetailMapper.changeSupplierStatus(supplierId, SupplierStatus.OFFLINE.value());
        }
    }

    @Override
    public List<SupplierSimpleBO> listSimple(SupplierSimpleBO supplierSimpleBO) {
        return supplierDetailMapper.listSimple(supplierSimpleBO);
    }

    @Override
    public Boolean checkSupplierName(String supplierName) {
        return supplierDetailMapper.countSupplierName(supplierName, null) > 0;
    }

    @Override
    public List<Long> getSupplierIdBySupplierStatus(Integer supplierStatus) {
        return supplierDetailMapper.getSupplierIdsBySupplierStatus(supplierStatus);
    }

    @Override
    public void offlineSupplierActivity(List<Long> supplierIds, Integer supplierStatus) {
        if (!Objects.equals(supplierStatus, SupplierStatus.STOP.value()) && Objects.equals(supplierStatus, SupplierStatus.OFFLINE.value())) {
            return;
        }
//        //下线满减活动
//        ServerResponseEntity<Void> handleDiscountOffline = discountFeignClient.handleSupplierOffline(supplierIds);
//        if (handleDiscountOffline.isFail()) {
//            throw new LuckException(handleDiscountOffline.getMsg());
//        }
//        //下线优惠券
//        ServerResponseEntity<Void> handleCouponOffline = couponFeignClient.handleSupplierOffline(supplierIds);
//        if (handleCouponOffline.isFail()) {
//            throw new LuckException(handleCouponOffline.getMsg());
//        }
    }

    @Override
    public PageVO<SupplierDetailVO> pageSupplier(PageDTO pageDTO, SupplierDetailDTO supplierDetailDTO, Long shopId) {
        //商家端 只显示有相同分类的供应商
        if(Objects.equals(supplierDetailDTO.getSysType(), SysTypeEnum.MULTISHOP.value())){
            ServerResponseEntity<List<Long>> idsResp = categoryShopFeignClient.getSupplierIdsByShopId(shopId);
            if (!idsResp.isSuccess()) {
                throw new LuckException(idsResp);
            }
            if(CollectionUtil.isEmpty(idsResp.getData())){
                PageVO<SupplierDetailVO> pageVO = new PageVO<>();
                pageVO.setList(new ArrayList<>());
                pageVO.setTotal(0L);
                pageVO.setPages(0);
                return pageVO;
            }
            return PageUtil.doPage(pageDTO, () -> supplierDetailMapper.listSupplierDetail(supplierDetailDTO,idsResp.getData()));
        }
        //平台端 显示全部供应商
        return PageUtil.doPage(pageDTO, ()->supplierDetailMapper.listSupplierDetail(supplierDetailDTO, null));

    }

    @Override
    public List<SupplierDetailVO> listSupplierByShopId(SupplierDetailDTO supplierDetailDTO, Long shopId) {
        //商家端 只显示有相同分类的供应商
        ServerResponseEntity<List<Long>> supplierIdsResp = categoryShopFeignClient.getSupplierIdsByShopId(shopId);
        if (!supplierIdsResp.isSuccess()) {
            throw new LuckException(supplierIdsResp);
        }
        if(CollUtil.isEmpty(supplierIdsResp.getData())){
            return new ArrayList<>();
        }
        return supplierDetailMapper.listSupplierDetail(supplierDetailDTO, supplierIdsResp.getData());

    }
    @Override
    public List<SupplierApiDetailVO> listSupplierDetailBySupplierIds(List<Long> supplierIds) {
        if (CollUtil.isEmpty(supplierIds)) {
            return new ArrayList<>();
        }
        return supplierDetailMapper.listSupplierDetailBySupplierIds(supplierIds);
    }

    /**
     * 添加供应商钱包
     * @param supplierId
     * @return
     */
    public void addSupplierInfo(Long supplierId) {
        SupplierExtension supplierExtension = new SupplierExtension();
        supplierExtension.setSupplierId(supplierId);
        supplierExtensionService.save(supplierExtension);

        SupplierWallet supplierWallet = new SupplierWallet();
        supplierWallet.setVersion(0L);
        supplierWallet.setZoneNum(SupplierWalletZoneConstant.ZERO);
        supplierWallet.setUnsettledAmount(0L);
        supplierWallet.setSettledAmount(0L);
        supplierWallet.setFreezeAmount(0L);
        supplierWallet.setTotalSettledAmount(0L);
        supplierWallet.setSupplierId(supplierId);
        supplierWalletMapper.save(supplierWallet);
    }

    /**
     * 检验供应商信息是否正确
     * @param supplierDetailDTO 供应商基本信息
     * @param isCreate true: 创建时校验， false: 更新时校验
     */
    private void checkSupplierInfo(SupplierDetailDTO supplierDetailDTO, Boolean isCreate) {
        if (!isCreate) {
            SupplierAuditingVO supplierAuditingVO = supplierAuditingService.getBySupplierId(supplierDetailDTO.getSupplierId());
            if (Objects.nonNull(supplierAuditingVO) && Objects.equals(supplierAuditingVO.getStatus(), AuditStatus.WAITAUDIT.value())) {
                throw new LuckException("供应商处于待审核状态无法修改信息");
            }
        }
        // 供应商店铺名称
        if (StrUtil.isNotBlank(supplierDetailDTO.getSupplierName())) {
            supplierDetailDTO.setSupplierName(supplierDetailDTO.getSupplierName().trim());
        }
        if(supplierDetailMapper.countSupplierName(supplierDetailDTO.getSupplierName(), supplierDetailDTO.getSupplierId()) > 0) {
            throw new LuckException("供应商名称已存在");
        }
        if (!isCreate) {
            // 更新供应商基本信息不用校验用户信息
            return;
        }
        // 手机号、邮箱
        if (StrUtil.isNotBlank(supplierDetailDTO.getEmail())) {
            supplierDetailDTO.setEmail(supplierDetailDTO.getEmail().trim());
        }
        if (StrUtil.isNotBlank(supplierDetailDTO.getContactPhone())) {
            supplierDetailDTO.setPhone(supplierDetailDTO.getContactPhone().trim());
        }
    }

    /**
     * 创建供应商初始账号
     * @param supplierDetailDTO
     * @param statusEnum
     */
    public void createSupplierAccount(SupplierDetailDTO supplierDetailDTO, StatusEnum statusEnum) {
        SupplierUser supplierUser = new SupplierUser();
        supplierUser.setSupplierId(supplierDetailDTO.getSupplierId());
        supplierUser.setHasAccount(1);
        supplierUser.setNickName(supplierDetailDTO.getUsername());
        supplierUserService.save(supplierUser, null);

        AuthAccountDTO authAccountDTO = new AuthAccountDTO();
        authAccountDTO.setEmail(supplierDetailDTO.getEmail());
        authAccountDTO.setPhone(supplierDetailDTO.getPhone());
        authAccountDTO.setUsername(supplierDetailDTO.getUsername());
        authAccountDTO.setPassword(supplierDetailDTO.getPassword().trim());
        authAccountDTO.setStatus(statusEnum.value());
        authAccountDTO.setSysType(SysTypeEnum.SUPPLIER.value());
        authAccountDTO.setCreateIp(IpHelper.getIpAddr());
        authAccountDTO.setTenantId(supplierDetailDTO.getSupplierId());
        authAccountDTO.setUserId(supplierUser.getSupplierUserId());
        authAccountDTO.setIsAdmin(UserAdminType.ADMIN.value());
        ServerResponseEntity<Long> save = accountFeignClient.save(authAccountDTO);
        if (!Objects.equals(save.getCode(), ResponseEnum.OK.value())) {
            throw new LuckException(save.getMsg());
        }
    }

    private Date getSaveEndOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.endOfDay(date));
        // 防止时间进位
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
}
